#!/usr/bin/perl
# 
# Exercise 11.4
# 
# Parse out the record types of a PDB file using regular expressions (as used in 
# Chapter 10) instead of iterating through an array of input lines (as in this chapter.)
#
# Answer to Exercise 11.4

# As mentioned in the text, this is perhaps not the best way to do this job.  Since each line
# of PDB files have the record type as the first field, it is very easy to just iterate through
# the lines and save the record types by looking at that field.  It is also space-efficient,
# since you only have to read in one line at a time from the file.  And some PDB files are
# quite large.  Nevertheless, as an exercise, the approach given here may be useful.  We'll
# follow the basic approach of Example 10-6.

use strict;
use warnings;

#
# Open a PDB file and read it into a scalar variable
#

# Plug in the filename of your choice here
my $pdbfile = 'pdb/pdb1a4o.ent';

open(PDBFILE, "$pdbfile") or die;

# It's nice to warn users if the program will seem unresponsive for a while
print "Reading PDB file $pdbfile ... this may take a minute ...";

my $pdbdata = join('', <PDBFILE>);

print "\n";

#
# Parse the record types into a hash data structure
#

my(%recordtypes) = (  );

# Note the regular expression:
# ([A-Z]+) finds the name of the record type (without trailing digits if any)
# [^\n]*\n find any number of non-newlines, up to the first newline

while( $pdbdata =~ /([A-Z]+)[^\n]*\n/gs ) {

	# $1 matches the parenthesized part of our regular expression
	# $& matches the entire matched string of our regular expression
	if( defined $recordtypes{$1} ) {
		$recordtypes{$1} .= $&;
	}else{
		$recordtypes{$1} = $&;
	}
}

#
# Interact with the user, asking for record types and showing the lines comprising them
#

# This while loop has two statements separated by a comma.  Such a list of statements will
# return the value of the last item in the list.
while( print("The record types for this file are:\n", join(" ", sort keys %recordtypes), "\n"),
	my $query = getuserinput("Show which record type?: "))
{

	if(defined $recordtypes{$query}) {
		print $recordtypes{$query},"\n";
	}else{
		print "The record type \"$query\" is not in the PDB files\n";
	}
}

exit;

################################################################################
# Subroutines
################################################################################
#
# getuserinput
#  - prompt the user for a one-line response
#    return null if response is an empty line, q, or quit
#    Otherwise, return answer (with leading and trailing whitespace removed)
#
sub getuserinput {
	my($prompt) = @_;

	print $prompt;
	my $ans = <STDIN>;
	chomp $ans;
	if($ans =~ /^\s*$/ or $ans =~ /^\s*q\s*$/i or $ans =~ /^\s*quit\s*$/i) {
		return '';
	}else{
		$ans =~ s/^\s*//;
		$ans =~ s/\s*$//;
		return $ans;
	}
}

